home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / jetset.1 / jetset.tar / draw.c < prev    next >
C/C++ Source or Header  |  1995-04-15  |  22KB  |  905 lines

  1. #include <stdio.h>
  2. #include <X11/Xlib.h>
  3.  
  4. #include "draw.h"
  5. #include "main.h"
  6. #include "data.h"
  7. #include "data_colors.h"
  8. #include "data_chars.h"
  9. #include "data_neighb.h"
  10. #include "data_sprite.h"
  11. #include "data_monsters.h"
  12. #include "widget.h"
  13. #include "game.h"
  14.  
  15. #include "chars.h"
  16. #include "monsters.h"
  17. #include "flash.xbm"
  18. #define NBFLASH (flash_height/16)
  19.  
  20. static Pixmap chars_pixmap;
  21. static Pixmap monsters_pixmap;
  22. static Pixmap flash_mask[NBFLASH];
  23. static Pixmap floor_pixmap;
  24. static Pixmap teleport_pixmap;
  25.  
  26. static int nb_rect;
  27. static int max_rect = 40;
  28. static Rectangle *rectangles;
  29.  
  30. bits32 mask[NMONSTERS][YSPRITE];
  31. /*
  32.  * Stored LSB first, i.e., bit 0 is the leftmost on screen.
  33.  */
  34.  
  35. void printbin (unsigned int v)
  36. {
  37.     int i;
  38.     for (i=0; i<32; i++) {
  39.     if (v & 0x80000000)
  40.         putchar ('X');
  41.     else
  42.         putchar (' ');
  43.     v <<= 1;
  44.     }
  45. }
  46.  
  47. #define MAX(x,y) (((x)>(y))?(x):(y))
  48. #define MIN(x,y) (((x)<(y))?(x):(y))
  49.  
  50. void add_rect (int x, int y, int w, int h)
  51. {
  52.     int i;
  53.     Rectangle *rec;
  54.  
  55.     if (nb_rect >= max_rect) {
  56.     max_rect = nb_rect + 10;
  57.     rectangles = (Rectangle *) realloc (rectangles,
  58.                         max_rect * sizeof (Rectangle));
  59.     if (rectangles == NULL) {
  60.         perror ("realloc");
  61.         exit (2);
  62.     }
  63.     }
  64.  
  65.     while (nb_rect) {                     /* merge rectangles */
  66.     rec = rectangles + nb_rect-1;                 /* start at end */
  67.     for (i=nb_rect-1; i>=0; i--, rec--) {
  68.         int rx = rec->x;
  69.         int ry = rec->y;
  70.         int rw = rec->w;
  71.         int rh = rec->h;
  72.         if (x<=rx+rw && rx<=x+w && y<=ry+rh && ry<=y+h) {
  73.         int nx = MIN(x,rx);
  74.         int ny = MIN(y,ry);
  75.         int nw = MAX(x+w,rx+rw)-nx;
  76.         int nh = MAX(y+h,ry+rh)-ny;
  77.         x = nx;
  78.         y = ny;
  79.         w = nw;
  80.         h = nh;
  81.         if (i != nb_rect-1)
  82.             rectangles[i] = rectangles[nb_rect-1];
  83.         nb_rect--;
  84.         break;
  85.         }
  86.     }
  87.     if (i < 0) /* none found */
  88.         break;
  89.     }
  90.     rectangles[nb_rect].x = x;
  91.     rectangles[nb_rect].y = y;
  92.     rectangles[nb_rect].w = w; 
  93.     rectangles[nb_rect].h = h;
  94.     nb_rect++;
  95. }
  96.  
  97.  
  98. void flush_rects ()
  99. {
  100.     int i;
  101.     Rectangle *rec = rectangles;
  102.  
  103.     for (i=0; i<nb_rect; i++) {
  104.     Update_Zone (canvas_widget, rec->x, rec->y, rec->w, rec->h);
  105.     rec++;
  106.     }
  107.     nb_rect = 0;
  108. }
  109.  
  110.  
  111.  
  112.  
  113.  
  114. void precompute_sprites ()
  115. {
  116.     int i, j;
  117.     unsigned char *ptr;
  118.  
  119.     if (sizeof (bits32) != 4) {
  120.     fprintf (stderr, "bits32 is %d bits !\n", 8*sizeof (bits32));
  121.     exit (2);
  122.     }
  123.     ptr = (unsigned char *) monsters_bits;
  124.     for (i=0; i<NMONSTERS; i++) {
  125.     for (j=0; j<YSPRITE; j++) {
  126.         mask[i][j] = (   ptr[0] 
  127.               | (ptr[1] << 8)
  128.               | (ptr[2] << 16)
  129.               | (ptr[3] << 24));
  130.         ptr += 4;
  131.     }
  132.     }
  133. }
  134.  
  135. static int cpc_col[32*3] = {
  136.     0x29<<10, 0x29<<10, 0x29<<10,                    /* white */
  137.     0x29<<10, 0x29<<10, 0x29<<10,              /* (same as white) */
  138.     0x1c<<10, 0x39<<10, 0x20<<10,                 /* seegreen */
  139.     0x3c<<10, 0x31<<10, 0x14<<10,                   /* pastelgold */
  140.     0x00<<10, 0x00<<10, 0x2b<<10,                     /* blue */
  141.     0x3f<<10, 0x00<<10, 0x28<<10,                   /* purpur */
  142.     0x00<<10, 0x28<<10, 0x32<<10,                /* bluegreen */
  143.     0x3f<<10, 0x26<<10, 0x26<<10,                /* purple (pink) */
  144.     0x3f<<10, 0x00<<10, 0x38<<10,             /* (same as purpur) */
  145.     0x3c<<10, 0x31<<10, 0x14<<10,           /* (same as 'pastelgold') */
  146.     0x3a<<10, 0x3a<<10, 0x00<<10,                 /* light yellow */
  147.     0x3e<<10, 0x3e<<10, 0x3e<<10,                  /* light white */
  148.     0x3f<<10, 0x00<<10, 0x00<<10,                /* light red */
  149.     0x3f<<10, 0x00<<10, 0x3a<<10,                /* light magenta */
  150.     0x3c<<10, 0x2a<<10, 0x00<<10,                   /* orange */
  151.     0x3b<<10, 0x1a<<10, 0x3b<<10,                /* past. magenta */
  152.     0x00<<10, 0x00<<10, 0x2b<<10,               /* (same as blue) */
  153.     0x1c<<10, 0x39<<10, 0x20<<10,             /* (same as 'seegreen') */
  154.     0x00<<10, 0x39<<10, 0x00<<10,                   /* lightgreen */
  155.     0x00<<10, 0x2f<<10, 0x3f<<10,              /* light bluegreen */
  156.     0x00<<10, 0x00<<10, 0x00<<10,                    /* black */
  157.     0x00<<10, 0x00<<10, 0x3c<<10,                /* lightblue */
  158.     0x00<<10, 0x2e<<10, 0x00<<10,                    /* green */
  159.     0x1e<<10, 0x1e<<10, 0x3e<<10,                  /* skyblue */
  160.     0x30<<10, 0x00<<10, 0x30<<10,                  /* magenta */
  161.     0x20<<10, 0x3d<<10, 0x21<<10,                  /* past. green */
  162.     0x2b<<10, 0x3c<<10, 0x00<<10,                   /* lemongreen */
  163.     0x1f<<10, 0x1a<<10, 0x3f<<10,              /* past. bluegreen */
  164.     0x29<<10, 0x05<<10, 0x05<<10,                      /* red */
  165.     0x30<<10, 0x00<<10, 0x3f<<10,               /* mauve (violet) */
  166.     0x30<<10, 0x2b<<10, 0x00<<10,                   /* yellow */
  167.     0x26<<10, 0x26<<10, 0x3c<<10,                   /* past. blue */
  168. };
  169.  
  170. #define floor_width 8
  171. #define floor_height 16
  172. static char floor_bits[] = {
  173.    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  174.    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  175. };
  176.  
  177. void draw_init ()
  178. {
  179.     static int initialized = 0;
  180.     if (!initialized) {
  181.     int i;
  182.     Pixmap tmp;
  183.     XGCValues gcv;
  184.     GC gc;
  185.  
  186.     initialized = 1;
  187.     chars_pixmap = XCreateBitmapFromData (display, canvas,
  188.                           chars_bits,
  189.                           chars_width, chars_height);
  190.     monsters_pixmap = XCreateBitmapFromData (display, canvas,
  191.                          monsters_bits,
  192.                          monsters_width,
  193.                          monsters_height);
  194.     floor_pixmap = XCreateBitmapFromData (display, canvas,
  195.                           floor_bits,
  196.                           floor_width,
  197.                           floor_height);
  198.     teleport_pixmap = XCreatePixmap (display, canvas, 32, 32, depth);
  199.  
  200.     tmp = XCreateBitmapFromData (display, canvas,
  201.                      flash_bits,
  202.                      flash_width,
  203.                      flash_height);
  204.     gcv.graphics_exposures = 0;
  205.     gc = XCreateGC (display, tmp, GCGraphicsExposures, &gcv);
  206.     for (i=0; i<NBFLASH; i++) {
  207.         flash_mask[i] = XCreatePixmap (display, canvas, 16, 16, 1);
  208.         XCopyArea (display, tmp, flash_mask[i], gc,
  209.                0, 16*i, 16, 16, 0, 0);
  210.     }
  211.     XFreeGC (display, gc);
  212.     XFreePixmap (display, tmp);
  213.  
  214.     rectangles = (Rectangle *) malloc (max_rect * sizeof (Rectangle));
  215.     if (rectangles == NULL) {
  216.         perror ("malloc");
  217.         exit (2);
  218.     }
  219.     nb_rect = 0;
  220.  
  221.     precompute_sprites ();
  222.     }
  223. }
  224.  
  225.  
  226. static void draw_char (int c,
  227.                int x,
  228.                int y)
  229. {
  230.     XGCValues gcv;
  231.     int fg = char_colors[c].fg;
  232.     int bg = char_colors[c].bg;
  233.     
  234.     if (!color_display && fg != 0 && bg != 0) {
  235.     if (fg == 3)
  236.         bg = 0;
  237.     else if (bg == 3)
  238.         fg = 0;
  239.     else {
  240.         int a, f, b;
  241.         a = 2-fg;
  242.         f = cpc_col[3*a] + cpc_col[3*a+1] + cpc_col[3*a+2];
  243.         a = 2-bg;
  244.         b = cpc_col[3*a] + cpc_col[3*a+1] + cpc_col[3*a+2];
  245.         if (f > b)
  246.         bg = 0;
  247.         else
  248.         fg = 0;
  249.     }
  250.     }
  251.     gcv.foreground = pixels[fg];
  252.     gcv.background = pixels[bg];
  253.     XChangeGC (display, gc_copyplane, GCForeground | GCBackground, &gcv);
  254.     XCopyPlane (display, chars_pixmap, canvas, gc_copyplane,
  255.         0, c*16, 16, 16, x, y, 1);
  256. }
  257.  
  258.  
  259. void xor_floor (int x, int y)
  260. {
  261.     XGCValues gcv;
  262.     gcv.foreground = pixels[1] ^ pixels[0];
  263.     gcv.background = pixels[2] ^ pixels[0];
  264.     gcv.clip_mask = None;
  265.     XChangeGC (display, gc_xorchar,
  266.            GCForeground | GCBackground | GCClipMask,
  267.            &gcv);
  268.     XCopyPlane (display, floor_pixmap, canvas, gc_xorchar,
  269.         0, 0, 8, 16, 2*x, 2*y, 1);
  270.     add_rect (2*x, 2*y, 8, 16);
  271. }
  272.  
  273.  
  274.  
  275. void xor_char (int c,
  276.            int x,
  277.            int y,
  278.            Pixmap mask,
  279.            int forcecolor)
  280. {
  281.     XGCValues gcv;
  282.     if (forcecolor) {
  283.     gcv.foreground = pixels[3] ^ pixels[0];
  284.     gcv.background = 0;
  285.     } else {
  286.     gcv.foreground = pixels[char_colors[c].fg] ^ pixels[0];
  287.     gcv.background = pixels[char_colors[c].bg] ^ pixels[0];
  288.     }
  289.     gcv.clip_mask = mask;
  290.     gcv.clip_x_origin = x;
  291.     gcv.clip_y_origin = y;
  292.     XChangeGC (display, gc_xorchar,
  293.            GCForeground | GCBackground | GCClipMask
  294.            | GCClipXOrigin | GCClipYOrigin, &gcv);
  295.     XCopyPlane (display, chars_pixmap, canvas, gc_xorchar,
  296.         0, c*16, 16, 16, x, y, 1);
  297. }
  298.  
  299. void xor_item (int val,
  300.            int x,
  301.            int y,
  302.            int maskno,
  303.            int forcecolor)
  304. {
  305.     xor_char (room_chars[room_no][val-1], 2*x, 2*y,
  306.           flash_mask[maskno%NBFLASH], forcecolor);
  307.     add_rect (2*x, 2*y, 16, 16);
  308. }
  309.  
  310.  
  311. int make_teleport_sprite (int sprite)
  312. {
  313.     int x, y, i;
  314.  
  315.     XFillRectangle (display, teleport_pixmap, gc_zero, 0, 0, 32, 32);
  316.     XCopyPlane (display, monsters_pixmap, teleport_pixmap, gc_three,
  317.         0, sprite*32, 32, 32, 0, 0, 1);
  318.     for (x=0; x<16; x++)
  319.     for (y=0; y<16; y++) {
  320. #ifdef NO_RAND48
  321.         extern int rand (void);
  322.         int a = rand () % 4;
  323. #else
  324.         extern long lrand48 (void);
  325.         long a = lrand48 () % 4;
  326. #endif
  327.         XPoint p[4];
  328.         p[0].x = 2*x;
  329.         p[0].y = 2*y;
  330.         p[1].x = 2*x+1;
  331.         p[1].y = 2*y;
  332.         p[2].x = 2*x;
  333.         p[2].y = 2*y+1;
  334.         p[3].x = 2*x+1;
  335.         p[3].y = 2*y+1;
  336.         XDrawPoints (display, teleport_pixmap, gc_and[a], p, 4,
  337.              CoordModeOrigin);
  338.     }
  339.     return -2;
  340. }
  341.  
  342.  
  343. void put_sprite (int sprite,
  344.          int x,
  345.          int y,
  346.          int c)
  347. {
  348.     if (sprite == -2) {
  349.     XCopyArea (display, teleport_pixmap, canvas, gc_xorplane[3],
  350.             0, 0, 32, 32, x, y);
  351.     } else {
  352.     XCopyPlane (display, monsters_pixmap, canvas, gc_xorplane[c&3],
  353.             0, sprite*32, 32, 32, x, y, 1);
  354.     }
  355.     add_rect (x, y, 32, 32);
  356. }
  357.  
  358. void put_sprite_noxor (int sprite,
  359.                int x,
  360.                int y,
  361.                int c)
  362. {
  363.     XCopyPlane (display, monsters_pixmap, canvas, gcs[c&3],
  364.         0, sprite*32, 32, 32, x, y, 1);
  365.     add_rect (x, y, 32, 32);
  366. }
  367.  
  368.  
  369. static void setink (int ink,
  370.             int val)
  371. {
  372.     XColor col;
  373.  
  374.     if (!color_display)
  375.     return;
  376.  
  377.     col.pixel = pixels[ink & 3];
  378.     col.flags = DoRed | DoGreen | DoBlue;
  379.     val &= 0x1f;
  380.     col.red = cpc_col[3*val];
  381.     col.green = cpc_col[3*val+1];
  382.     col.blue = cpc_col[3*val+2];
  383.     XStoreColor (display, colormap, &col);
  384. }
  385.  
  386.  
  387. void flash_dead (int x, int y, int n)
  388. {
  389.     if (color_display) {
  390.     XColor col;
  391.     int val = 3*(room_colors[room_no][2] & 0x1f);
  392.     int red = cpc_col[val];
  393.     int green = cpc_col[val+1];
  394.     int blue = cpc_col[val+2];
  395.     int i = NB_FLASHES_COLOR - n;
  396.     col.pixel = pixels[0];
  397.     col.flags = DoRed | DoGreen | DoBlue;
  398.     col.red = red+(0xffff-red)*i/(NB_FLASHES_COLOR-1);
  399.     col.green = green+(0xffff-green)*i/(NB_FLASHES_COLOR-1);
  400.     col.blue = blue+(0xffff-blue)*i/(NB_FLASHES_COLOR-1);
  401.     XStoreColor (display, colormap, &col);
  402.     XFlush (display);
  403.     } else {
  404.     int i = 5*(NB_FLASHES_MONO - n);
  405.     XDrawRectangle (display, XtWindow (canvas_widget),
  406.             gc_xorplane[3],
  407.             x+16-i, y+16-i, 2*i, 2*i);
  408.     }
  409. }
  410.  
  411. void draw_automove (int x,
  412.             int y,
  413.             int len,
  414.             int dir,
  415.             int offset)
  416. {
  417.     int of = (dir == -1) ? offset : (4-offset);
  418.     XDrawLine (display, canvas, gc_dash[of&3],
  419.            x, y, x+len-1, y);
  420.     XDrawLine (display, canvas, gc_dash[of&3],
  421.            x, y+1, x+len-1, y+1);
  422.     XDrawLine (display, XtWindow (canvas_widget), gc_dash[of&3],
  423.            x, y, x+len-1, y);
  424.     XDrawLine (display, XtWindow (canvas_widget), gc_dash[of&3],
  425.            x, y+1, x+len-1, y+1);
  426.     /*add_rect (x, y, len, 2);*/
  427. }
  428.  
  429.  
  430. void draw_liane_pixels (XPoint *points, int n)
  431. {
  432.     
  433.     XDrawPoints (display, canvas, gc_xorplane[3],
  434.          points, n, CoordModeOrigin);
  435.     XDrawPoints (display, XtWindow (canvas_widget), gc_xorplane[3],
  436.          points, n, CoordModeOrigin);
  437. }
  438.  
  439. void draw_thread (int x, int y, int cnt)
  440. {
  441.     if (cnt) {
  442.     XSegment seg[2];
  443.  
  444.     seg[0].x1 = 4*x+16;
  445.     seg[0].y1 = 2*y;
  446.     seg[0].x2 = 4*x+16;
  447.     seg[0].y2 = 2*(y+cnt)-1;
  448.     seg[1].x1 = 4*x+17;
  449.     seg[1].y1 = 2*y;
  450.     seg[1].x2 = 4*x+17;
  451.     seg[1].y2 = 2*(y+cnt)-1;
  452.     XDrawSegments (display, canvas, gc_xorplane[1],
  453.                seg, 2);
  454.     add_rect (seg[0].x1, seg[0].y1, 2, 2*cnt);
  455.     /*XDrawSegments (display, XtWindow (canvas_widget), gc_xorplane[1],
  456.                seg, 2);*/
  457.     }
  458. }
  459.  
  460.  
  461.  
  462.  
  463. void draw_room ()
  464. {
  465.     int i, j;
  466.     XGCValues gcv;
  467.  
  468.     gcv.foreground = pixels[0];
  469.     XChangeGC (display, gc_copyplane, GCForeground | GCBackground, &gcv);
  470.     XFillRectangle (display, canvas, gc_copyplane, 0, 0, 512, 256);
  471.     for (j=0; j<YROOM; j++) {
  472.     int y;
  473.     y = j*16;
  474.     for (i=0; i<XROOM; i++) {
  475.         int x;
  476.         int val;
  477.         x = i*16;
  478.         val = room_data[j][i];
  479.         if (val != I_NOTHING && val != I_ITEM) {
  480.         draw_char (room_chars[room_no][val-1], x, y);
  481.         }
  482.     }
  483.     }
  484.  
  485.     XFlush (display);
  486.     Update_Screen (canvas_widget);
  487.     setink (3, 0x0b);
  488.     for (i=0; i<3; i++)
  489.     setink (2-i, room_colors[room_no][i]);
  490.     XtVaSetValues (roomname_widget,
  491.                    XtNlabel, (XtArgVal) room_name[room_no],
  492.                    NULL);
  493.     XFlush (display);
  494. }
  495.  
  496.  
  497. void show_nb_items_taken ()
  498. {
  499.     char buf[10];
  500.     extern int nb_items_taken;
  501.  
  502.     if (discovery_mode)
  503.     *buf='\0';
  504.     else
  505.     sprintf (buf, "%d", nb_items_taken);
  506.     XtVaSetValues (itemstaken_widget,
  507.                    XtNlabel, (XtArgVal) buf,
  508.                    NULL);
  509. }
  510.  
  511. void show_nb_lives ()
  512. {
  513.     char buf[10];
  514.     extern int nb_lives;
  515.  
  516.     if (discovery_mode)
  517.     *buf='\0';
  518.     else
  519.     sprintf (buf, "%d", nb_lives);
  520.     XtVaSetValues (lives_widget,
  521.                    XtNlabel, (XtArgVal) buf,
  522.                    NULL);
  523. }
  524.  
  525. void show_tripswitch (int state)
  526. {
  527.     char *s;
  528.  
  529.     switch (state) {
  530.     case 0: s = " "; break;
  531.     case 1: s = "Trip Switch On"; break;
  532.     case 2: s = "Trip Switch Off"; break;
  533.     }
  534.     XtVaSetValues (tripswitch_widget,
  535.                    XtNlabel, (XtArgVal) s,
  536.                    NULL);
  537. }
  538.  
  539.  
  540. #if 0
  541. void PutPlayer (w, event, params, num_params)
  542.     MyWidget w;
  543.     XEvent *event;
  544.     String *params;
  545.     Cardinal *num_params;
  546. {
  547.     extern void newpos ();
  548.     extern int debugging;
  549.  
  550.     if (debugging)
  551.     newpos (event->xbutton.x/2, event->xbutton.y/2);
  552. }
  553. #endif
  554.  
  555.  
  556.  
  557. int sprites_collide (int spr1,
  558.              int x1,
  559.              int y1,
  560.              int spr2,
  561.              int x2,
  562.              int y2)
  563. {
  564.     int yb1, yb2, ny;
  565.     int shift;
  566.     int i;
  567.     bits32 *p1, *p2;
  568.  
  569.     if (   x1>=x2+XSPRITE || x2>=x1+XSPRITE
  570.     || y1>=y2+YSPRITE || y2>=y1+YSPRITE
  571.     || spr1 == -1 || spr2 == -1)
  572.     return 0;
  573.     if (x1>x2) {
  574.     int t;
  575.     t = x1; x1 = x2; x2 = t;
  576.     t = y1; y1 = y2; y2 = t;
  577.     t = spr1; spr1 = spr2; spr2 = t;
  578.     }
  579.     shift = x2-x1;
  580.     if (y1>y2) {
  581.     yb1 = 0;
  582.     yb2 = y1-y2;
  583.     ny = YSPRITE-yb2;
  584.     } else {
  585.     yb2 = 0;
  586.     yb1 = y2-y1;
  587.     ny = YSPRITE-yb1;
  588.     }
  589.     p1 = mask[spr1] + yb1;
  590.     p2 = mask[spr2] + yb2;
  591.     if (shift == 0) {
  592.     for (i=ny; i>0; i--) {
  593.         if ((*p1++) & (*p2++))
  594.         return 1;
  595.     }
  596.     } else {
  597.     for (i=ny; i>0; i--) {
  598.         if (((*p1++) >> shift) & (*p2++))            /* LSB first !!! */
  599.         return 1;
  600.     }
  601.     }
  602.     return 0;
  603. }
  604.  
  605. int pixel_collide (int spr, int xs, int ys, int x, int y)
  606. {
  607.     int shift;
  608.     bits32 v;
  609.  
  610.     if (   x<xs || x>=xs+XSPRITE
  611.     || y<ys || y>=ys+YSPRITE
  612.     || spr == -1)
  613.     return 0;
  614.     v = mask[spr][y-ys];
  615.     shift = x-xs;
  616.     if (shift == 0)
  617.     return (v & 3);
  618.     else
  619.     return ((v >> shift) & 3);
  620. }
  621.  
  622. void draw_rescue (int cnt)
  623. {
  624.     static char buf[20];
  625.  
  626.     sprintf (buf, "%4d To Rescue   ", cnt);
  627.     XDrawImageString (display, canvas,
  628.               gc_string, 180, 32, buf, strlen (buf));
  629.     XDrawImageString (display, XtWindow (canvas_widget),
  630.               gc_string, 180, 32, buf, strlen (buf));
  631. }
  632.  
  633.  
  634.  
  635. void move_boat ()
  636. {
  637.     XCopyArea (display, canvas, canvas,
  638.            gc_black,
  639.            8, 80, 8*0x2a, 2*0x50, 0, 80);
  640.     XCopyArea (display, XtWindow (canvas_widget), XtWindow (canvas_widget),
  641.            gc_black,
  642.            8, 80, 8*0x2a, 2*0x50, 0, 80);
  643.     XFlush (display);
  644. }
  645.  
  646. void move_rocket ()
  647. {
  648.     XCopyArea (display, canvas, canvas,
  649.            gc_black,
  650.            160, 2, 192, 254, 160, 0);
  651.     XCopyArea (display, XtWindow (canvas_widget), XtWindow (canvas_widget),
  652.            gc_black,
  653.            160, 2, 192, 254, 160, 0);
  654.     XFlush (display);
  655. }
  656.  
  657. void move_tree ()
  658. {
  659.     XCopyArea (display, canvas, canvas,
  660.            gc_black,
  661.            8*0x12, 44, 8*0x18, 2*0x49, 8*0x12, 46);
  662.     XCopyArea (display, XtWindow (canvas_widget), XtWindow (canvas_widget),
  663.            gc_black,
  664.            8*0x12, 44, 8*0x18, 2*0x49, 8*0x12, 46);
  665.     XFlush (display);
  666. }
  667.  
  668. void clear_tree ()
  669. {
  670.     XFillRectangle (display, canvas, gcs[0], 8*0x12, 44, 8*0x18, 2+2*0x49);
  671.     Update_Screen (canvas_widget);
  672.     XFlush (display);
  673. }
  674.  
  675. void show_time (int cnt)
  676. {
  677.     static char buf[20];
  678.     extern int time_ascent;
  679.  
  680.     if (discovery_mode) {
  681.     extern GC gc_time_white;
  682.     extern int time_widget_w, time_widget_h;
  683.  
  684.     XFillRectangle (display, time_widget->my.store, gc_time_white,
  685.             0, 0, time_widget_w, time_widget_h);
  686.     XFillRectangle (display, XtWindow (time_widget), gc_time_white,
  687.             0, 0, time_widget_w, time_widget_h);
  688.     } else {
  689.     sprintf (buf, "%02d:%02d:%02d", cnt/3600, (cnt/60)%60, cnt%60);
  690.     XDrawImageString (display, time_widget->my.store,
  691.               gc_time, 5, time_ascent, buf, strlen (buf));
  692.     XDrawImageString (display, XtWindow (time_widget),
  693.               gc_time, 5, time_ascent, buf, strlen (buf));
  694.     }
  695. }
  696.  
  697.  
  698.  
  699.  
  700.  
  701. unsigned char dr_jetset[] = { /* a600 */
  702.     0x54, 0x56, 0x35, 0x25, 0x25, 0x25, 0x13, 0x91,
  703.     0x90, 0x99, 0x0b, 0x0d, 0x1d, 0x2a, 0x39, 0x31,
  704.     0x42, 0x45, 0x92, 0xa0, 0xba, 0x9a, 0x9c, 0x2c,
  705.     0x2a, 0x29, 0x31, 0x32, 0x22, 0x23, 0x27, 0x27,
  706.     0x03, 0x9b, 0x9a, 0x0f, 0x0d, 0x1b, 0x2d, 0x3d,
  707.     0x3f, 0x37, 0x04, 0x76, 0x0b, 0x3a, 0x4c, 0x9a,
  708.     0x0a, 0x21, 0x13, 0x29, 0x02, 0x10, 0x2a, 0x3a,
  709.     0x71, 0x11, 0x37, 0x04, 0x92, 0xa2, 0xc3, 0xb4,
  710.     0x01, 0x12, 0x67, 0x30, 0x29, 0x1b, 0x1c, 0x0b,
  711.     0x90, 0x92, 0x94, 0x11, 0x19, 0x2f, 0x3b, 0x1a,
  712.     0x59, 0x73, 0x11, 0x24, 0x01, 0x91, 0xa9, 0xaa,
  713.     0xba, 0xac, 0x0f, 0x1a, 0x19, 0x30, 0x40, 0x62,
  714.     0x22, 0x17, 0x17, 0x17, 0x12, 0x9f, 0xaf, 0xaf,
  715.     0x0c, 0x39, 0x30, 0x72, 0x52, 0x7a, 0x39, 0x2a,
  716.     0xa0, 0x99, 0xf9, 0xc9, 0xda, 0xca, 0xbb, 0xfa,
  717.     0xdb, 0xa0, 0xd0, 0xda, 0xba, 0xb1, 0x90, 0xdb,
  718.     0xa0, 0xba, 0x0a, 0x39, 0x32, 0x11, 0x04, 0x91,
  719.     0x99, 0x0d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d,
  720.     0x19, 0x10, 0x11, 0x55, 0x45, 0x15, 0x15, 0x15,
  721.     0x02, 0xaf, 0x9d, 0x0d, 0x0d, 0x1a, 0x30, 0x22,
  722.     0x35, 0x25, 0x25, 0x02, 0x91, 0x99, 0x0a, 0x2b,
  723.     0x19, 0x20, 0x21, 0x23, 0x9e, 0x0c, 0x2b, 0x20,
  724.     0x21, 0x37, 0x27, 0x17, 0x14, 0xaf, 0x0f, 0x0f,
  725.     0x0a, 0x19, 0x29, 0x31, 0x47, 0x27, 0x27, 0x04,
  726.     0xaf, 0x9e, 0x0f, 0x1c, 0x39, 0x41, 0x12, 0x07,
  727.     0x14, 0x44, 0xdf, 0x9f, 0x1a, 0x2a, 0x40, 0x77,
  728.     0x27, 0x15, 0xaf, 0xaf, 0xaf, 0xcf, 0xba, 0xa9,
  729.     0xa2, 0x23, 0x72, 0x41, 0x21, 0x20, 0x9b, 0x2c,
  730.     0x0f, 0xff, 0xaf, 0x43, 0x30, 0x4b, 0x00,
  731. };
  732.  
  733. unsigned char dr_dot[] = { /* a6e7 */
  734.     0x20, 0x19, 0x0a, 0x99, 0xa0, 0x91, 0x02, 0x11, 0x00,
  735. };
  736.  
  737. unsigned char dr_line[] = { /* a6f0 */
  738.     0x71, 0x71, 0x71, 0x00,
  739. };
  740.  
  741. #define XSCR 512
  742. #define YSCR 256
  743.  
  744. static void draw_rel (int x, int y, unsigned char *array)
  745. {
  746.     unsigned char c;
  747.     while (c = *array++) {
  748.     int dx, dy;
  749.     dx = (c >> 4) & 0xf;
  750.     if (dx & 8)
  751.         dx = -(dx & 7);
  752.     dy = c & 0xf;
  753.     if (dy & 8)
  754.         dy = -(dy & 7);
  755.     dx *= 2;
  756.     dy *= 2;
  757.     XDrawLine (display, canvas, gc_white, x, 400-y, x+dx, 400-(y+dy));
  758.     x += dx;
  759.     y += dy;
  760.     }
  761. }
  762.  
  763.  
  764.  
  765. static void draw_present ()
  766. {
  767.     draw_rel (0x064, 0x12c, dr_jetset);
  768.     draw_rel (0x08c, 0x186, dr_dot);
  769.     draw_rel (0x14a, 0x113, dr_dot);
  770.     draw_rel (0x0b4, 0x163, dr_line);
  771.     draw_rel (0x154, 0x163, dr_line);
  772. }
  773.  
  774.  
  775.  
  776. static int scroll_pos;
  777. static char scroll_mess[] = " \
  778. JET SET WILLY  -  The Final Frontier  .  .  .  .  .  .  .  .  .  .  .  .  .  \
  779. version 1.0.1, by <Florent.Guillaume@ens.fr>  .  .  Linux port by <jmd@dcs.ed.ac.uk>  .  .  .  .  \
  780. Control keys are:   \
  781. LEFT=,/z/o/j/leftarrow    \
  782. RIGHT=./x/p/l/rightarrow    \
  783. JUMP=k/space/uparrow  \
  784. .  .  .  .  .  .  \
  785. Right!  .  .  .  .  .  .  \
  786. This is the adventure of MINER WILLY retold.  \
  787. Strange things did happen to Willy when he explored his huge mansion.  \
  788. No expense has been spared in allowing you to recreate the \
  789. magical escapade of Willy on his travels.  All you need is stamina and guts \
  790. to overcome all the seemingly impossible odds  .  .  .  \
  791. GOOD LUCK!  \
  792. .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  \
  793. Watch out for the Yacht!  .  .  .  .  .  .  .  \
  794. Beware of the Sewers!  .  .  .  .  .  .  .  \
  795. Willy in Space?  .  .  .  .  .  .  .  \
  796. Willy or won't he?  .  .  .  .  .  .  .  \
  797. Boldly go where no Willy has gone before!  .  .  .  .  .  .  \
  798. .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  \
  799. Original Amstrad version copyright 1985 Software Projects, \
  800. programming by D.P.Rowson & S.Wetherill, \
  801. from an idea by Matthew-JET-SET-Smith  \ 
  802. .   .   .    .    .     .      .         .           .              . \
  803.                       \
  804.   \0\0";
  805.  
  806. extern int scroll_ascent;
  807. extern int scroll_w;
  808. extern int scroll_h;
  809.  
  810. void do_scroll ()
  811. {
  812.     static Pixmap tmp_pix = 0;
  813.  
  814.     if (tmp_pix == 0) {
  815.     tmp_pix = XCreatePixmap (display, canvas, 2*scroll_w, scroll_h, depth);
  816.     }
  817. #define SPD 2
  818.     XCopyArea (display, canvas, canvas, gc_black, SPD, YSCR-scroll_h,
  819.            XSCR-SPD, scroll_h, 0, YSCR-scroll_h);
  820.     scroll_pos += SPD;
  821.     if ((scroll_pos%scroll_w) < SPD) {
  822.     if (scroll_mess[scroll_pos/scroll_w] == '\0')
  823.         scroll_pos = 0;
  824.     XDrawImageString (display, tmp_pix, gc_scroll,
  825.               0, scroll_ascent, scroll_mess+(scroll_pos/scroll_w), 2);
  826.     }
  827.     XCopyArea (display, tmp_pix, canvas, gc_black,
  828.            scroll_pos%scroll_w, 0, SPD, scroll_h, XSCR-SPD, YSCR-scroll_h);
  829.     Update_Zone (canvas_widget, 0, YSCR-scroll_h, XSCR, scroll_h);
  830.     XFlush (display);
  831. }
  832.  
  833.  
  834. void present ()
  835. {
  836.     enable_colormap (0);
  837.     XFillRectangle (display, canvas, gc_black, 0, 0, XSCR, YSCR);
  838.     draw_present ();
  839.     Update_Screen (canvas_widget);
  840.     XtVaSetValues (roomname_widget,
  841.                    XtNlabel, (XtArgVal) "",
  842.                    NULL);
  843.     scroll_pos = -SPD;
  844. }
  845.  
  846.  
  847. static int colormap_enabled = 0;
  848. static int colormap_wanted = 0;
  849.  
  850. static void switch_colormap (int on)
  851. {
  852.     extern Widget toplevel;
  853.     extern int private_colormap;
  854.  
  855.     if (private_colormap) {
  856.     Window wins[2];
  857.  
  858.     wins[on?0:1] = XtWindow (canvas_widget);
  859.     wins[on?1:0] = XtWindow (toplevel);
  860.     XSetWMColormapWindows (display, XtWindow (toplevel), wins, 2);
  861.     }
  862. }
  863.  
  864. void set_colormaps (int on)
  865. {
  866.     if (on && !colormap_wanted && colormap_enabled)
  867.     switch_colormap (1);
  868.     else if (!on && colormap_wanted && colormap_enabled)
  869.     switch_colormap (0);
  870.     colormap_wanted = on;
  871. }
  872.  
  873. void enable_colormap (int enable)
  874. {
  875.     if (enable && !colormap_enabled && colormap_wanted) {
  876.     set_colormaps (1);
  877.     } else if (!enable && colormap_enabled && colormap_wanted) {
  878.     set_colormaps (0);
  879.     }
  880.     colormap_enabled = enable;
  881. }
  882.  
  883.  
  884.  
  885.  
  886.  
  887.  
  888.  
  889. int errorhandler (Display *disp, XErrorEvent *err)
  890. {
  891.     extern void emergency(int);
  892.     char msg[100];
  893.     XGetErrorText (disp, err->error_code, msg, 98);
  894.     strcat(msg, "\n");
  895.     write (2, msg, strlen(msg));
  896.     emergency (0);
  897. }
  898.  
  899. int ioerrorhandler (Display *disp)
  900. {
  901.     extern void emergency(int);
  902.     emergency (0);
  903. }
  904.  
  905.